package com.sudo.service.admin.runnable;

import com.sudo.common.component.SpringContextUtil;
import com.sudo.common.service.BaseService;
import com.sudo.common.utils.ThreadLocalUtil;
import com.sudo.dao.admin.entity.SysServerNodeJob;
import com.sudo.rpc.api.model.CallTask;
import com.sudo.service.admin.rpc.provider.RmiRegistryServiceImpl;
import com.sudo.service.tldata.ThreadLocalObject;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;

/**
 * 每一个定时任务都对应一个子线程
 */
@Getter
@Setter
@Slf4j
public class RpcMethodRunnable extends BaseService implements Runnable{
    private Integer id;
    private String server;
    private String beanName;
    private String methodName;
    private String params;
    private String callbackFun;
    private String logStatus;
    private String mailStatus;
    private String mailAddress;
    private Object targetBean;
    private Method method;

    public RpcMethodRunnable(Integer id,String server, String beanName, String methodName) {
        this.id = id;
        this.server = server;
        this.beanName = beanName;
        this.methodName = methodName;
    }

    public RpcMethodRunnable(SysServerNodeJob sysServerNodeJob) {
        this.id = sysServerNodeJob.getId();
        this.server = sysServerNodeJob.getServer();
        this.beanName = sysServerNodeJob.getBeanName();
        this.methodName = sysServerNodeJob.getMethodName();
        this.params = sysServerNodeJob.getMethodParams();
        this.callbackFun = sysServerNodeJob.getCallbackFun();
        this.logStatus = sysServerNodeJob.getLogStatus();
        this.mailStatus = sysServerNodeJob.getMailStatus();
        this.mailAddress = sysServerNodeJob.getMailAddress();
        init();
    }

    public void init() {
        try {
            String simpleName = StringUtils.uncapitalize(RmiRegistryServiceImpl.class.getSimpleName());

            targetBean = SpringContextUtil.getBean(simpleName);
            method = targetBean.getClass().getDeclaredMethod("callServer", CallTask.class);
            // 使方法可访问
            ReflectionUtils.makeAccessible(method);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        log.info("定时任务开始执行 - id：{}，server：{}，bean：{}，方法：{}，参数：{}，回调：{}",id,server,beanName,method,params,callbackFun);
        long startTime = System.currentTimeMillis();
        try {
            Map<String, Object> jobConfigMap = ThreadLocalObject.initJobConfigMap(this);
            ThreadLocalUtil.setTlMap(jobConfigMap);
            String[] split = server.split(":");
            CallTask callTask = new CallTask(split[0],Integer.parseInt(split[1]),beanName,methodName,params,callbackFun);
            method.invoke(targetBean, callTask);
        } catch (Exception e) {
            throw new RuntimeException("任务["+id+"]自动执行失败");
        }
        long endTime = System.currentTimeMillis();
        log.info("定时任务执行结束 - id：{}，server：{}，bean：{}，方法：{}，参数：{}，回调：{}，耗时：{}毫秒",id,server,beanName,method,params,callbackFun,(endTime-startTime));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        RpcMethodRunnable that = (RpcMethodRunnable) o;
        return Objects.equals(id, that.id)
                && Objects.equals(server,that.server)
                && Objects.equals(beanName, that.beanName)
                && Objects.equals(methodName, that.methodName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id,server,beanName, methodName);
    }


}
